package common

import (
	"crypto/md5"
	"crypto/sha1"
	"crypto/sha256"
	"crypto/sha512"
	"encoding/binary"
	"io"
	urlparse "net/url"
	"regexp"
	"strings"
)

var (
	IMAGE_FILTER = `(http|https)://\S+\.(jpg|png|gif|bmp)`
)

type UrlFilter interface {
	Match(url string) bool
}
type RegexpFilter struct {
	patern string
}

func NewRegexpFilter(patern string) *RegexpFilter {
	return &RegexpFilter{patern}
}
func (self *RegexpFilter) Match(url string) bool {
	matched, err := regexp.MatchString(self.patern, url)
	if err != nil {
		return false
	}
	return matched
}

const (
	BLOOM_SIZE = 1000 * 10000
)

type BloomFilter struct {
	bloom_seq [BLOOM_SIZE]uint8
}

func (self *BloomFilter) filter(url string) [6]uint32 {
	md5_hash := md5.New()
	sha1_hash := sha1.New()
	sha244_hash := sha256.New224()
	sha256_hash := sha256.New()
	sha384_hash := sha512.New384()
	sha512_hash := sha512.New()

	io.WriteString(md5_hash, url)
	io.WriteString(sha1_hash, url)
	io.WriteString(sha244_hash, url)
	io.WriteString(sha256_hash, url)
	io.WriteString(sha384_hash, url)
	io.WriteString(sha512_hash, url)

	v0 := binary.BigEndian.Uint32(md5_hash.Sum(nil)) % (BLOOM_SIZE - 1)
	v1 := binary.BigEndian.Uint32(sha1_hash.Sum(nil)) % (BLOOM_SIZE - 1)
	v2 := binary.BigEndian.Uint32(sha244_hash.Sum(nil)) % (BLOOM_SIZE - 1)
	v3 := binary.BigEndian.Uint32(sha256_hash.Sum(nil)) % (BLOOM_SIZE - 1)
	v4 := binary.BigEndian.Uint32(sha384_hash.Sum(nil)) % (BLOOM_SIZE - 1)
	v5 := binary.BigEndian.Uint32(sha512_hash.Sum(nil)) % (BLOOM_SIZE - 1)
	return [6]uint32{v0, v1, v2, v3, v4, v5}
}
func (self *BloomFilter) Set(url string) {
	filter := self.filter(url)
	for _, v := range filter {
		self.bloom_seq[v] = 1
	}
}
func (self *BloomFilter) Match(url string) bool {
	filter := self.filter(url)
	count := 0
	for _, v := range filter {
		if self.bloom_seq[v] == 1 {
			count++
		}
	}
	if count == 6 {
		return true
	}
	return false
}
func NormalizeUrl(url string, domain string) string {
	var u *urlparse.URL
	var err error
	if u, err = urlparse.Parse(url); err != nil {
		return ""
	}
	if u.Scheme == "" {
		u.Scheme = "http"
	}
	if u.Host == "" && domain != "" {
		u.Host = domain
	}
	u = u.ResolveReference(u)
	return strings.ToLower(u.String())
}
